home *** CD-ROM | disk | FTP | other *** search
/ Zoom 2 / Zoom - Release 2 (1996)(Active Software)[!].iso / texts / arexxguide / editors / arx_help.edge < prev    next >
Text File  |  1994-03-30  |  18KB  |  481 lines

  1. /** $VER: ARx_Help.edge 2.0 (10 Mar 1994)
  2.  ** by Robin Evans
  3.  **
  4.  ** Display the ARexxGuide page for the word currently under the
  5.  ** cursor.  Will call ARx_Setup.rexx if env: variables are not set.
  6.  **
  7.  ** Add the following line (change Q if you'd like) to user.keyboard.
  8.  **
  9.  ** KEYCOM   KEY="Help"      Q="Shift"        COMMAND ARx_help
  10.  **
  11.  ** You may want to add the following lines to your S:user-startup file.
  12.  **
  13.  **   RXLIB amigaguide.library 0 -30
  14.  **
  15.  **  The AmigaGuide/path environmental variable must include the directory
  16.  **  where arx_guide.xref is located.
  17.  **/
  18.  
  19. signal on syntax
  20. signal on break_c
  21. signal on halt
  22. signal on failure
  23.  
  24. options results
  25. parse arg LkUp
  26.  
  27. call addlib('rexxsupport.library',0,-30)
  28. call addlib('amigaguide.library',-1,-30)
  29.  
  30. TRUE=1; FALSE=0
  31.  
  32.    /* Load the cross-ref file. Function returns quickly if the file is  **
  33.    ** already loaded, but -- like ADDLIB() it can return true even if   **
  34.    ** the file isn't available, so we check by looking for a known node.*/
  35. call DisplayStatus('ARx_Help: Checking .xref files...')
  36. do Attempt = 1
  37.     call LoadXref('ARx_Guide.xref')
  38.    if getxref('TRACEOPT1') = 10 then do   /* Leave below */
  39.       /* Did this in a loop just to be able to use signal for a no-load */
  40.       if Attempt = 2 then
  41.           signal XRefError
  42.       else if 'ARx_Setup.rexx'('HELP',,address()) ~= 0 then signal XRefError
  43.    end
  44.    else leave Attempt
  45. end
  46.  
  47. /* Add any extra files included in the env: variable.                */
  48. ExtraXRef = GetEnv('ARexxGuide/XRFiles')
  49. do i = 1 for words(ExtraXRef)
  50.       /* 'Call' because we don't care about errors here.             */
  51.    call loadxref(word(ExtraXRef, i))
  52. end
  53.  
  54. call DisplayStatus('ARexxGuide online help system...')
  55.  
  56.    /* It isn't used in the setup provided here, but it's possible to    **
  57.    ** just pass a word as an argument to this routine and get a lookup  **
  58.    ** on that.                                                          */
  59. if LkUp = '' then do
  60.       /* Get the current line and position. Editor's commands are all   **
  61.       ** in subroutines and not in the main code.                       */
  62.    HLine = GetCLine()
  63.    CurPos = GetCurPos()
  64.       /* Show the index requester if it's a blank line */
  65.    if HLine = '' | verify(HLine, ' ;') = 0 then do
  66.       call ShowInfo(,, CurPos, Kwd)
  67.       signal CleanExit
  68.    end
  69.  
  70.       /* Cut a single clause out of preceding clauses                   */
  71.    SemPos = lastpos(';', HLine, CurPos) + 1
  72.       /* This will break if a semicolon is used within a string         **
  73.       ** but checking for that seems like overkill.                     */
  74.    if SemPos > 1 then do
  75.       if SemPos < CurPos + 1 then do
  76.          parse var HLine =SemPos HLine ';'
  77.          CurPos = CurPos - SemPos + 1
  78.       end
  79.    end
  80.       /* Cut it out of following clauses                                 */
  81.    else
  82.       parse var HLine HLine ';'
  83.  
  84.    /* The current keyword is used within MChar select clause             */
  85.    Kwd = upper(word(HLine, 1))
  86.  
  87.                                               /* Hex characters: SpTbRt    */
  88.       /* Check for special characters -- operators, quotation marks, etc */
  89.    MChar = pos(substr(HLine,CurPos,1), '+-/*%|&^><=,;:~)("''?!.'||'20090a'x)
  90.    select
  91.       when MChar = 0 then do     /* It isn't one of the chars */
  92.          /* Look for whole word if it isn't a special character */
  93.          LkUp = GetCWord(HLine, CurPos)
  94.       end
  95.       when MChar <= 5 then
  96.          select
  97.             when MChar <= 2 then       /* + or - */
  98.                if Kwd = 'PARSE' then
  99.                   LkUp = 'PARSETMP5'
  100.                else
  101.                   LkUp = 'ARITHMETIC'
  102.             when MChar <= 4 then do    /* / or * */
  103.                   /* This picks up the three characters surrounding a '*' or '/' */
  104.                ComChar = substr(HLine, max(1, CurPos - 1), 3)
  105.                if pos('/*', ComChar) + pos('*/', ComChar) > 0 then
  106.                   LkUp = 'COMMENT'
  107.                else
  108.                   LkUp = 'ARITHMETIC'
  109.             end
  110.             otherwise
  111.                 LkUp = 'ARITHMETIC'        /* % */
  112.          end
  113.       when MChar <= 13 then
  114.          select
  115.             when MChar <= 8 then do    /* | or & or ^ */
  116.                   /* This picks up the three characters surrounding token */
  117.                ComChar = substr(HLine, max(1, CurPos - 1), 3)
  118.                if pos('||', ComChar) > 0 then
  119.                   LkUp = 'CONCATENATION'
  120.                else
  121.                   LkUp = 'LOGICAL'
  122.             end
  123.             when MChar <= 10 then    /* < or > */
  124.                LkUp = 'COMPARISON'
  125.             when MChar = 11 then    /* = */
  126.                if Kwd = 'PARSE' then
  127.                   LkUp = 'PARSETMP5'
  128.                else if symbol(strip(left(HLine, max(1, CurPos-1)))) == 'BAD' then
  129.                   LkUp = 'COMPARISON'
  130.                else
  131.                   LkUp = 'ASSIGNMENT'
  132.             when MChar = 12 then    /* , */
  133.                LkUp = 'COMMA'
  134.             otherwise               /* ; */
  135.                LkUp = 'SEMICOLON'
  136.          end
  137.       when MChar <= 19 then
  138.          select
  139.             when MChar = 14 then    /* : */
  140.                LkUp = 'LABEL'
  141.             when MChar = 15 then do /* ~ */
  142.                   /* is the next character a comparison operator? */
  143.                if pos(substr(HLine, CurPos , 2), '~=~>~<') > 0 then
  144.                   LkUp = 'COMPARISON'
  145.                else
  146.                   LkUp = 'LOGICAL'
  147.             end
  148.             when MChar <=17 then    /* ) or ( */
  149.                if Kwd = 'PARSE' then
  150.                   LkUp = 'PARSETMP5'
  151.                else
  152.                   LkUp = 'PAREN'
  153.             otherwise               /* " or ' */
  154.                LkUp = 'STRING'
  155.          end
  156.       otherwise
  157.          select
  158.             when MChar = 20 then    /* ? */
  159.                if Kwd = 'TRACE' then
  160.                   LkUp = 'TRACEOPT1'
  161.                else
  162.                   LkUp = '?'
  163.             when MChar = 21 then    /* ! */
  164.                if Kwd = 'TRACE' then
  165.                   LkUp = 'TRACEOPT2'
  166.                else
  167.                   LkUp = '!'
  168.             when MChar = 22 then do   /* . -- dot  */
  169.                   /* Get the surrounding ARexx token */
  170.                StPos = verify(' 'HLine, '+-|/&=~\><^,;:()"'' ', 'M', lastpos(' ', ' 'HLine, CurPos))
  171.                Token = substr(HLine, StPos, verify(HLine' ', '+-|/&=~\><^,;:()"'' ', M, CurPos) - StPos)
  172.                select
  173.                    when Token = '.' then
  174.                       if Kwd = 'PARSE' then
  175.                          LkUp = 'PARSETMP2'
  176.                       else
  177.                          LkUp = Token
  178.                    when datatype(Token, 'N') then
  179.                        LkUp = 'NUMBER'
  180.                    when datatype(Token, 'S') then
  181.                        if datatype(left(Token,1),'M') | verify(Token, '!@#$', 'M') = 1
  182.                            then LkUp = 'COMPVAR'
  183.                    otherwise
  184.                       LkUp = Token
  185.                 end
  186.             end
  187.             otherwise               /* At a space or EOL */
  188.                if CurPos >= wordindex(HLine, 1) then
  189.                   LkUp = GetCWord(HLine, CurPos)
  190.                else do
  191.                   call ShowInfo(HLine,, CurPos, Kwd)
  192.                   signal CleanExit
  193.                end
  194.          end
  195.    end
  196.  
  197.  
  198.    /* Check for special words like `command' in `address command'       **
  199.    ** and most of the subkeywords in instructions like DO.              */
  200.    if word(HLine, 1) ~= LkUp then do CheckOpt = 1 for 1  /* Let's us leave */
  201.       if GetXRef(LkUp) = 10 | find('ARG PULL UPPER COMMAND', upper(LkUp)) > 0 then do
  202.          if word(GetXRef(Kwd),3) = 2 then select
  203.             when Kwd = 'DO' then do
  204.                SpecWord = find('UNTIL WHILE TO FOR BY FOREVER ', upper(LkUp))
  205.                if SpecWord > 0 then
  206.                   LkUp = word('DOOPT4 DOOPT4 DOOPT2 DOOPT3 DOOPT2 DOOPT5', SpecWord)
  207.             end
  208.             when Kwd = 'PARSE' then do
  209.                SpecWord = find('ARG PULL EXTERNAL NUMERIC SOURCE VERSION VALUE VAR WITH', upper(LkUp))
  210.                if SpecWord > 0 then do
  211.                   LkUp = 'PARSESRC'SpecWord
  212.                   if SpecWord = 9 then
  213.                      LkUp = 'PARSESRC7'
  214.                end
  215.                else
  216.                   LkUp = 'PARSETMP1'
  217.             end
  218.             when Kwd = 'OPTIONS' then
  219.                if find('RESULTS PROMPT FAILAT CASHE ON OFF', upper(LkUp)) > 0 then
  220.                   LkUp = Kwd
  221.             when Kwd = 'TRACE' then
  222.                if verify(upper(right(LkUp,1)), 'IRACLENOBS') = 0 then
  223.                   LkUp = 'TRACEOPT'
  224.             when Kwd = 'SIGNAL' then
  225.                if find('ON OFF', upper(LkUp)) >0 then
  226.                   LkUp = 'SIGTRAP'
  227.                else if pos('BREAK_', upper(LkUp)) = 1 then
  228.                   LkUp = 'BREAK_'
  229.                else
  230.                   LkUp = 'SIGTRAN'
  231.             when upper(LkUp) = 'UPPER' then
  232.                if Kwd ~= 'UPPER' then
  233.                   LkUp = 'UPPER()'
  234.             when Kwd = 'ADDRESS' then
  235.                if abbrev(word(HLine, 2), LkUp) then do
  236.                   LkUp = Kwd
  237.                   leave CheckOpt  /* so we don't get address() */
  238.                end
  239.             otherwise
  240.          end
  241.          if GetXRef(LkUp'()') ~= 10 then
  242.             LkUp = LkUp'()'
  243.       end
  244.    end
  245. end
  246. else do     /* Word was supplied as argument to the script */
  247.    upper LkUp
  248.    CurPos = 1; HLine = LkUp
  249. end
  250.  
  251. XRVal = upper(GetXRef(LkUp))
  252. if find('10 NODE/K', XRVal) > 0 then do
  253.    if ShowInfo( HLine, LkUp, CurPos, Kwd ) = 0 then signal CleanExit
  254.     else XRVal = upper(GetXRef(LkUp))
  255. end
  256.  
  257. if ~abbrev(word(XRVal,2), '"ARX_') then
  258.    Src = 'Other ref:'
  259. else
  260.    Src = 'ARexxGuide:'
  261. call DisplayStatus(Src upper(LkUp) '['word('Explanation Function Instruction', word(getxref(LkUp), 3)+1)']')
  262.  
  263. signal on error
  264. call DisplayAG(LkUp)
  265. signal off error
  266.  
  267. CleanExit:
  268.     /* Since it can cause severe problems, it's removed when not needed */
  269. call remlib('amigaguide.library')
  270. call EditorExit()
  271. exit 0
  272.  
  273. /*************************************************************************
  274. ** Error routines.                                                      */
  275.  
  276. XRefError:
  277.    ErrMsg = 'Unable to load the cross-reference file ARx_Guide.xref\'
  278.    if ~exists('env:amigaguide/path') then
  279.       ErrMsg = ErrMsg || 'Your environmental variable "amigaguide/path" is not set.\'
  280.    else
  281.       ErrMsg = ErrMsg '  Be sure to include that file''s directory in env:amigaguide/path.\'
  282.    ErrMsg = ErrMsg '  The .xref file may be put into the current directory or into\',
  283.    '  any directory included in the amigaguide/path environmental variable.'
  284.    call PutErrMsg(SIGL, ErrMsg)
  285.    exit 6
  286. NoCmd:
  287.    call PutErrMsg(SIGL, 'Can''t read environmental variable "env:arexxguide/AGcmd".\',
  288.              '  That variable must hold the name of the command you use\',
  289.              '  to show AmigaGuide files.')
  290.    exit 7
  291. Syntax:
  292.    call PutErrMsg(SIGL, '   Syntax error #'rc ':' errortext(rc))
  293.    exit 9
  294. Failure:
  295.    call PutErrMsg(SIGL, '   Command "'sourceline(SIGL)'" failed.')
  296.     exit 10
  297. Halt:
  298. Break_C:
  299.    call PutErrMsg(SIGL, '   Execution halted.')
  300.     exit 8
  301. Error:
  302.    call PutErrMsg(SIGL, '   Command error in display routine: RC =' rc'.\\',
  303.              '  The name of your AmigaGuide viewer may not be properly set, or\',
  304.              '  an .xref file might have been loaded for a database not located\',
  305.              '  in one of the directories in env:AmigaGuide/path.\',
  306.              '  Type rx ARx_Setup at a shell prompt to run the setup program again.')
  307.     exit 9
  308. PutErrMsg:
  309.    call trace b
  310.    ErrMsg ='Sorry an enexpected error has occurred in line' arg(1)'.\\'arg(2)
  311.    signal off syntax
  312.    signal off halt
  313.    signal off break_c
  314.    WinHi = 59 + CountChar('\', ErrMsg) * 11
  315.    call DisplayStatus('ARx_Help macro error.')
  316.    if open(6ErrWin, 'raw:0/0/640/'WinHi'/Arx_Help Error/SCREEN *') then do
  317.       call writeln(6ErrWin, translate(ErrMsg,'0a'x, '\'))
  318.       call writech(6ErrWin, '0a'x'        -- Press any key -- ')
  319.       call readch(6ErrWin)
  320.    end
  321.    call EditorExit()
  322.    return 0
  323.  
  324. exit 0
  325.  
  326. /*************************************************************************
  327. ** General utility routines                                             */
  328.  
  329. GetAGCmd: procedure
  330.         /* Calls the setup program if env:ARexxGuide/AGCmd is not set       */
  331.     AGCmd = GetEnv('ARexxGuide/AGCmd')
  332.    if AGCmd = '' then do
  333.        call DisplayStatus('Please wait... Running setup routine')
  334.       if 'ARx_Setup.rexx'('HELP',,address()) ~= 0 then
  335.          signal NoCmd
  336.         else
  337.             AGCmd = GetEnv('ARexxGuide/AGCmd')
  338.     end
  339.     return AGCmd
  340.  
  341. ShowInfo:
  342.       /* The env: var ShowFullHelp determines whether a simple editor     **
  343.       ** requester is used, or a complex rexxarplib window that displays  **
  344.       ** far more information about the current line, but is also slow.   */
  345.    if getenv('ARexxGuide/ShowFullHelp') ~= '1' then do
  346.       if BoolReq(upper(LkUp) 'not found.','Show ARexxGuide index?') then do
  347.          LkUp = 'ARx_NdxCont'
  348.          return 1
  349.       end
  350.       else
  351.           return 0
  352.    end
  353.    else do
  354.          /* Show that we're doing something */
  355.       call DisplayStatus(LkUp 'not found. Checking clause...')
  356.  
  357.          /* The .rexx part of the name has to be added because the default **
  358.          ** extension is set by editor: .TTX, .edge, etc. Since this       **
  359.          ** is set up for different editors, it's stored with the generic  **
  360.          ** extension.                                                     */
  361.       return 'ARx_RArpInfoWin.rexx'(HLine,LkUp,CurPos,Kwd,SetAddress(),SetExecStr(),GetWinInfo())
  362.    end
  363.  
  364. CountChar:
  365.    return length(arg(2)) - length(compress(arg(2), arg(1)))
  366.  
  367. GetEnv: procedure
  368.       /* Arguments:                                                     **
  369.       **   arg(1) := The name of the variable to retrieve               **
  370.       ** Returns     a string                                           */
  371.  
  372.         /* Use external function of same name if it's available           */
  373.     if show('L', 'rexxarplib.library') then
  374.         return 'GetEnv'(arg(1))
  375.       /*  OPEN()  will fail if variable is not defined. Null will be    **
  376.       ** returned in that case                                          */
  377.    if open(6Env, 'env:'arg(1), 'R') then do
  378.       EnvVar = readln(6Env)
  379.       call close 6Env
  380.    end
  381.    else EnvVar = ''
  382.    return EnvVar
  383.  
  384. Tab2Space:  procedure
  385.    parse arg TSize, Line
  386.    tpos=pos('09'x,Line);
  387.    do while tpos>0;
  388.       Line=insert('',Line, tpos, min(1, tpos//TSize)*(TSize-tpos//TSize));
  389.       tpos=pos('09'x, Line,tpos+1);
  390.    end;
  391. return translate(Line,' ','09'x)
  392.  
  393.  
  394. /***********************************************************************
  395. ** Editor-specific commands.                                          **
  396. **        These function calls are used elsewhere to make it easier to    **
  397. **    use the same script for different editors.                      **
  398. **                                                                    **
  399. ** For help in customizing the macro for a different editor see       **
  400. ** ARexxGuide Tutorials section: Building a help macro                */
  401.  
  402. GetCLine: procedure
  403.    'DisableUser'
  404.    'GetEnvVar _FE_TabList'
  405.    TabSize = pos('T',result)        /* Hmm. Assumes that all tabs are same size */
  406.     'copy line resultbuff'
  407.       /* CurPos won't match ARexx count if tabs are used        */
  408.    return Tab2Space(TabSize, strip(result,'T', '0a'x))
  409.  
  410. GetCurPos: procedure
  411.    'GetEnvVar _WE_Column'
  412.    CurPos = result + 1
  413.    'EnableUser'
  414.     return CurPos
  415.  
  416. GetCWord: procedure
  417.         /* Use default version for testing */
  418.       /* Send back current word */
  419.    parse arg Line, CPos
  420.        /* list of valid word-separator charaters: space, operator, spec char */
  421.    SepChar = ' +-*/%|&~=><^,;:()."''\'
  422.       /* Back up in line if Current position is not an alpha character  or digit */
  423.    do while (verify(substr(Line,CPos,1), SepChar || '0a'x)=0) & (CPos>1)
  424.       CPos = CPos - 1
  425.    end
  426.       /* Cut off word at space _or_ any of the operator or special characters     */
  427.    Word = reverse(left(Line,verify(Line' ',SepChar,'M',CPos) - 1))
  428.    return reverse(left(Word,verify(Word' ',SepChar,'M', max(1,length(Word) + 1 - CPos))-1))
  429.  
  430.         /* Send back current word */
  431.             'copy word rb'
  432.             'copy word back rb'
  433.  
  434. DisplayStatus:
  435.         /* Put message in title bar of editor */
  436.     'WindowTitle "'arg(1)'"'
  437.     return 0
  438.  
  439. BoolReq:
  440.         /* Present a Yes/No requester                                      **
  441.         ** Arguments:                                                      **
  442.         **    arg(1)    := Titlebar text                                    **
  443.         **    arg(2)   := Message in body of requester                     */
  444.     if show('L', 'rexxreqtools.library') then
  445.         return rtezrequest(arg(2), '_Yes|_No', arg(1))
  446.      'RequestChoice TITLE "'arg(1)'" "'arg(2)'"'
  447.    return result
  448.  
  449. GetWinInfo: procedure
  450.         /* Return Information about window                                 **
  451.         **     Format of returned value:                                    **
  452.         **           word 1 = x position                                   **
  453.         **           word 2 - y position                                   **
  454.         **           word 3 = name of public screen                        */
  455.     'window'
  456.     parse var result 'X ' x ',' 'Y ' y ','
  457.     'GetEnvVar _GE_ScreenName'
  458.     return x y result
  459.  
  460. EditorExit:
  461.         /* Used for any editor-specific commands that should be issued on  **
  462.         ** exit.                                                           */
  463.     'EnableUser'
  464.     return 0
  465.  
  466. SetExecStr:
  467.         /* The string returned by this function is used in the rexxarplib  **
  468.         ** window to send link commands to AmigaGuide.                     */
  469.     return 'address ARX_ARP quit; Help section'
  470.  
  471. SetAddress:
  472.         /* Address used as target of the commands from rarp window         */
  473.     return address()
  474.  
  475. DisplayAG:
  476.         /* Show the node in AmigaGuide viewer. Missing env: will call**
  477.        ** error handler which runs the setup prg. and then passes   **
  478.        ** control back to here.                                     */
  479.  
  480.     'Help' arg(1)
  481.     return 0